package com.orange.lswidget.widgets.musicplayer.service;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import com.orange.lswidget.widgets.musicplayer.MusicPlayerClient;
import com.orange.lswidget.widgets.musicplayer.MusicPlayerManager;
import com.orange.lswidget.widgets.musicplayer.entry.MusicPlayer;
import com.orange.util.Constants;
import com.orange.util.LogHelper;
import com.orange.util.MusicPreferences;
import com.orange.util.MusicUtils;

public class MusicLSWidgetService extends Service {
	private static final String	TAG							= "MusicLSWidgetService";

	private static final int	DELAY_TO_CHANGE_MUSIC_STATE	= 100;

	private ServiceConnection	mConnection					= new MusicServiceConnection();
	private BroadcastReceiver	mReceiver					= new InnerMusicBroadcastReceiver();

	private MusicPlayerManager	mMpManager;
	private MusicPlayer			mMp;
	private MusicPlayerClient	mMpClient;
	private IMusicPlayerService	mMpService;
	private BroadcastReceiver	mMusicRFReceiver;
	private Context				mContext;

	private boolean				mIsHeadsetPlugged			= false;
	private H					mH							= null;

	public static void startService(Context context) {
		Intent service = new Intent(context, MusicLSWidgetService.class);
		context.startService(service);
	}

	public static void stopService(Context context) {
		Intent service = new Intent(context, MusicLSWidgetService.class);
		context.stopService(service);
	}

	
	class InnerMusicBroadcastReceiver extends BroadcastReceiver {
		/* (non-Javadoc)
		 * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
		 */
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			LogHelper.v("loop", "onReceive. ACTION: " + action);

			if (action.startsWith("com.android")) {
				handleMusicAction(action);
			} else if (action.startsWith("android.intent.action")) {
				handleExternalAction(intent, action);
			} else if (action.startsWith("com.lockscreen")) {
				handleLockscreenAction(action);
			}
		}
	}

	private void handleExternalAction(Intent intent, String action) {
		if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
			int plugged = intent.getIntExtra("state", 0);
			mIsHeadsetPlugged = plugged > 0 ? true : false;

			if (mH != null) {
				boolean hasDelay = mH.hasMessages(DELAY_TO_CHANGE_MUSIC_STATE);
				if (hasDelay) {
					return;
				}
			}

			if (mMpClient != null) {
				mMpClient.setHeadsetPlugged(mIsHeadsetPlugged);
				mMpClient.updateMusicSlatStatus();
			}
		} else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
			mMpClient.updateMusicSlatStatus();
		}
	}

	private void handleMusicAction(String action) {

		if (mMp.getPlaybackComplete().equals(action)) {
			mMpClient.setPlaybackCompleteStatus(true);
		} else if (mMp.getTogglepauseAction().equals(action)) {
			MusicUtils.updateMusicTrackSelected(mContext, "true");
			LogHelper.w(TAG, "TogglepauseAction broadcast won't update UI !");
			return;
		} else if (action.equals(mMp.getPlaystateChanged())) {

			if (mIsHeadsetPlugged) {
				if (mH != null) {
					Message msg = mH.obtainMessage(DELAY_TO_CHANGE_MUSIC_STATE);
					mH.sendMessageDelayed(msg, 1200);
				}
			}
			
		}
		// Commented off, as it's empty. -HMH 20120223.
//		else if (action.equals(mMp.getMetaChanged())
//				|| action.equals(mMp.getQueueChanged())) {
//
//		}

		// else if (mMp.isMusicActions(action)) {
		// action: playstatechanged/metachanged/queuechanged
		// for headset
		// /**********/
		// boolean playing = mMpService.isPlaying();
		// boolean fromUser = MusicPreferences
		// .isMusicTrackChangeByUser(mContext);
		// /**********/
		// if (mH != null) {
		// Message msg = mH.obtainMessage(DELAY_TO_CHANGE_MUSIC_STATE);
		// mH.sendMessageDelayed(msg, 1200);
		// }
		// }

		if (mMpClient != null) {
			mMpClient.updateMusicSlatStatus();
		}
	}

	private void handleLockscreenAction(String action) {
		if (Constants.ACTION_LOCKSCREEN_LOCK.equals(action)) {
			// reslove bug:
			// 1. stop music service
			// 2. lock screen and awake
			// 3. plug headset into phone
			// Expect result: music slat should display, and it contains
			// trackName, artistName etc.
			bindService(mContext);

			MusicPreferences.setLockScreenLoad(mContext, 1);
			if (mMpClient != null) {
				mMpClient.updateMusicSlatStatus();
			}
		} else if (Constants.ACTION_LOCKSCREEN_UNLOCK.equals(action)) {
			unbindService(mContext);
			MusicPreferences.setLockScreenLoad(mContext, 0);
			LogHelper.d("chunlei", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Constants.ACTION_LOCKSCREEN_UNLOCK. mMpClient.setMusicSlatOpened(false);" );
			mMpClient.setMusicSlatOpened(false);
			mMpClient.setHeadsetPlugged(mIsHeadsetPlugged);
			// resolve bug:
			// 1.lock screen and awake.
			// 2.open musicslat and pause it
			// 3. unlock screen 4. lock screen
			// Expect result: music slat should be hidden.
			if (mMpService != null && !mMpService.isPlaying()) {
				if (mMpClient != null) {
					mMpClient.updateMusicSlatStatus();
				}
			}
		} else if (Constants.ACTION_MUSIC_UNLOCK.equals(action)) {
			long albumId = -1;
			if (mMpService != null) {
				albumId = mMpService.getAlbumId();
			}
			mMpManager.startMusicPlayerActivity(mContext, albumId);
		} else if (Constants.ACTION_MUSIC_SLAT_OPENED.equals(action)) {
			LogHelper.d("chunlei", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Constants.ACTION_MUSIC_SLAT_OPENED mMpClient.setMusicSlatOpened(true);" );
			mMpClient.setMusicSlatOpened(true);
		} else if (Constants.ACTION_MUSIC_SLAT_CLOSED.equals(action)) {
			LogHelper.d("chunlei", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Constants.ACTION_MUSIC_SLAT_CLOSED mMpClient.setMusicSlatOpened(false);" );
			mMpClient.setMusicSlatOpened(false);
		}
	}

	class MusicServiceConnection implements ServiceConnection {
		public void onServiceConnected(ComponentName name, IBinder service) {
			LogHelper.d(TAG, "onServiceConnected. ");
//			mMpClient =  MusicPlayerClient.getInstance(mContext, service);
			mMpClient =  new MusicPlayerClient(mContext, service);
			mMpClient.updateMusicSlatStatus();

			mMpService = MusicPlayerClient.getSystemMPService();
			initIntentFilter();
		}

		public void onServiceDisconnected(ComponentName arg0) {
			LogHelper.d(TAG, "onServiceDisconnected. ");
			mMpService = null;
		}
	}

	@Override
	public void onCreate() {
		super.onCreate();
		mContext = getApplicationContext();
		MusicPreferences.init(mContext);

		mMpManager = MusicPlayerManager.getInstance(mContext);
		mMp = mMpManager.createMusicPlayer();
		mMusicRFReceiver = new MusicBroadcastReceiver();

		bindService(mContext);

		mH = new H();

	}

	private void initIntentFilter() {
		IntentFilter filter = new IntentFilter();
		filter.addAction(mMp.getPlaystateChanged());
		filter.addAction(mMp.getMetaChanged());
		
		// Remove the Queue changed action, as Noonhill 
		// broadcast a lot of this stuff.
		// And it should be good not to listen for the Queue change.
//		filter.addAction(mMp.getQueueChanged());
		filter.addAction(mMp.getPlaybackComplete());
		filter.addAction(mMp.getTogglepauseAction());
		filter.addAction(mMp.getPauseAction());
		filter.addAction(mMp.getPreviousAction());
		filter.addAction(mMp.getNextAction());

		filter.addAction(Constants.ACTION_MUSIC_UNLOCK);
		filter.addAction(Constants.ACTION_MUSIC_SLAT_OPENED);
		filter.addAction(Constants.ACTION_MUSIC_SLAT_CLOSED);
		filter.addAction(Constants.ACTION_LOCKSCREEN_UNLOCK);
		filter.addAction(Constants.ACTION_LOCKSCREEN_LOCK);
		filter.addAction(Intent.ACTION_HEADSET_PLUG);
		// filter.addAction(Intent.ACTION_SCREEN_ON);
		filter.addAction(Intent.ACTION_LOCALE_CHANGED);
		// filter.addAction("com.orange.music.play_stop");
		// filter.addAction("com.orange.music.next");
		// filter.addAction("com.orange.music.previous");
		registerReceiver(mReceiver, filter);

		IntentFilter musicRfFilter = new IntentFilter();
		musicRfFilter.addAction(Constants.ACTION_MUSIC_NEXT_LONGCLICK);
		musicRfFilter.addAction(Constants.ACTION_MUSIC_NEXT_CLICK);
		musicRfFilter.addAction(Constants.ACTION_MUSIC_PREV_LONGCLICK);
		musicRfFilter.addAction(Constants.ACTION_MUSIC_PREV_CLICK);
		registerReceiver(mMusicRFReceiver, musicRfFilter);
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onDestroy() {
		unregisterReceiver(mReceiver);
		unregisterReceiver(mMusicRFReceiver);
		mH.removeCallbacksAndMessages(null);

		disconnectService(mContext);
		super.onDestroy();
	}

	/**
	 * bind to IMediaPlaybackService
	 * @param context
	 */
	private void bindService(Context context) {
		Intent service = new Intent();
		service.setComponent(mMp.getMpComponentName());
		context.startService(service);
		context.bindService(service, mConnection, Context.BIND_AUTO_CREATE);
	}

	public void unbindService(Context context) {
		try {
			context.unbindService(mConnection);
		} catch (Exception e) {
			LogHelper.e(TAG, "unbindService. ", e);
		}
	}

	public void disconnectService(Context context) {
		LogHelper.v(TAG, "Music service destroyed.");
		Intent service = new Intent();
		service.setComponent(mMp.getMpComponentName());
		context.stopService(service);
	}

	class H extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case DELAY_TO_CHANGE_MUSIC_STATE:
				if (mMpClient != null) {
					mMpClient.updateMusicSlatStatus();
				}
				break;
			default:
				break;
			}
		}
	}
}
